<template>
    <div class="avatar">
        <el-avatar fit="cover" shape="circle" :size="50">
            <el-image v-if="userStore.account.avatarUrl" :src="userStore.account.avatarUrl" fit="cover">
                <template #error>
                    <el-icon :size="30"><User/></el-icon>
                </template>
            </el-image>
            <el-image v-else fit="cover">
                <template #error>
                    <el-icon :size="30"><User/></el-icon>
                </template>
            </el-image>
            <div class="el-upload-action">
                <el-icon v-show="userStore.account.avatarUrl" @click.stop="handleInZoomPreview"><zoom-in/></el-icon>
                <el-icon>
                    <el-upload :accept="imageTypes" class="avatar-uploader" ref="uploadRef"
                               :auto-upload="false" :limit="2" :show-file-list="false"
                               :on-change="changeSize">
                        <Plus/>
                    </el-upload>
                </el-icon>
            </div>
        </el-avatar>
        <el-image-viewer hide-on-click-modal v-if="imagePreviewVisible" @close="closePreview"
                         :url-list="[userStore.account.avatarUrl]"/>
        <el-dialog title="裁剪头像" width="80%" align-center
                   v-model="cropperDialog" @close="closeCropper"
        >
            <div style="height:40em; width: 100%;display: flex;justify-content: space-between;align-items: center">
                <vueCropper
                    class="crop-box"
                    ref="cropper"
                    :img="option.img"
                    :outputSize="option.size"
                    :outputType="option.outputType"
                    :info="option.info"
                    :full="option.full"
                    :canMove="option.canMove"
                    :canMoveBox="option.canMoveBox"
                    :original="option.original"
                    :autoCrop="option.autoCrop"
                    :fixed="option.fixed"
                    :fixedNumber="option.fixedNumber"
                    :centerBox="option.centerBox"
                    :infoTrue="option.infoTrue"
                    :fixedBox="option.fixedBox"
                    :mode="option.mode"
                    @imgLoad="onImageLoad"
                ></vueCropper>
                <div class="avatar-upload-preview">
                    <el-avatar fit="cover" :size="250" :src="imageCrop.url"/>
                </div>
            </div>
            <template #footer>
                <span class="dialog-footer">
                    <span>
                        <el-button :icon="Crop" @click="cropImage"></el-button>
                        <el-button :icon="Plus" @click="changeScale(1)"></el-button>
                        <el-button :icon="Minus" @click="changeScale(-1)"></el-button>
                        <el-button :icon="RefreshLeft" @click="$refs.cropper.rotateLeft()"></el-button>
                        <el-button :icon="RefreshRight" @click="$refs.cropper.rotateRight()"></el-button>
                    </span>
                    <span>
                        <el-button @click="cropperDialog = false">取消</el-button>
                        <el-button type="primary" @click="uploadAvatar"> 确认 </el-button>
                    </span>
                </span>
            </template>
        </el-dialog>
    </div>
</template>

<script setup>
import {reactive, ref} from "vue";

import {Crop, Minus, Plus, RefreshLeft, RefreshRight, User, ZoomIn} from "@element-plus/icons-vue";

import "vue-cropper/dist/index.css";
import {VueCropper} from "vue-cropper";

import {useUserStore} from '@/stores/user'
import {getAccountApi, uploadAccountAvatarApi} from "@/apis/account";
import {getHeadUploadPresigned, uploadByPresignedUrl} from "@/apis/file";

const userStore = useUserStore()

//上传图片的类型
const imageTypes = "image/png,image/jpg,image/jpeg";
//获取上传组件
const uploadRef = ref()

//裁剪框是否展示
let cropperDialog = ref(false);

//获取裁剪图片组件
const cropper = ref();

//裁剪图片的配置
const option = reactive({
    img: "", // 裁剪图片的地址
    info: true, // 裁剪框的大小信息
    outputSize: 1, // 裁剪生成图片的质量
    outputType: "jpeg", // 裁剪生成图片的格式
    canScale: true, // 图片是否允许滚轮缩放
    autoCrop: true, // 是否默认生成截图框
    canMoveBox: true, // 截图框能否拖动
    fixedBox: false, // 固定截图框大小 不允许改变
    fixed: true, // 是否开启截图框宽高固定比例
    fixedNumber: [1, 1], // 截图框的宽高比例
    full: false, // 是否输出原图比例的截图
    original: false, // 上传图片按照原始比例渲染
    centerBox: true, // 截图框是否被限制在图片里面
    mode: "contain", //图片的默认渲染方式
    infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
});

//裁剪的图片
const imageCrop = reactive({})

//获取裁剪的图片
const cropImage = () => {
    cropper.value.getCropBlob(blob => {
        imageCrop.file = blob
        imageCrop.url = window.URL.createObjectURL(blob)
    })
}
//vue-cropper加载图片的状态，成功success,失败fail
const onImageLoad = status => {
    if (status === "success") {
        setTimeout(() => {
            cropImage()
        }, 0)
    }
}
//关闭裁剪框
const closeCropper = () => {
    imageCrop.file = ""
    imageCrop.url = ""
}
//改变大小
const changeScale = (num) => {
    num = num || 1;
    cropper.value.changeScale(num);
}
//上传中
const changeSize = (UploadFile, UploadFileList) => {
    //判断上传格式
    const typeArr = imageTypes.split(",")
    let flag = false
    for (const type of typeArr) {
        if (UploadFile.raw.type.includes(type)) {
            flag = true
            break
        }
    }
    if (!flag) {
        ElMessage.error("很抱歉您上传的不是png,jpg,jpeg格式")
        return false;
    }
    if (UploadFile.raw.size / 1024 / 1024 > 2) {
        ElMessage.error("您上传的图片大小超过了2MB")
        return false;
    }
    UploadFileList.splice(0, 2)
    cropperDialog.value = true;
    //这里将图片转化为base64位格式为图片进行裁剪
    const reader = new FileReader();
    reader.onload = e => {
        //将图片绑定到裁剪组件的img中
        option.img = e.target.result;
    };
    //拿到图片的base64
    reader.readAsDataURL(UploadFile.raw);
};

//上传头像点击了确认按钮
const uploadAvatar = async () => {
    if (!imageCrop.file) {
        ElMessage.error("请先裁剪图片")
        return;
    }
    const file = new File(
        [imageCrop.file],
        "avatar" + (new Date()).valueOf() + "." + imageCrop.file.type.slice(imageCrop.file.type.lastIndexOf('/') + 1),
        {type: imageCrop.file.type, lastModified: Date.now()}
    )
    // await uploadAccountAvatarApi(file)
    const url = await getHeadUploadPresigned(file.name);
    await uploadByPresignedUrl(url.data, file)
    await uploadAccountAvatarApi(url.data.slice(0, url.data.lastIndexOf('?')))
    const res = await getAccountApi()
    userStore.account = res.data
    ElMessage.success("更新头像成功")
    cropperDialog.value = false;
};

//预览
let imagePreviewVisible = ref(false)
const handleInZoomPreview = () => {
    imagePreviewVisible.value = true
}
const closePreview = () => {
    imagePreviewVisible.value = false
}

</script>

<style lang="scss" scoped>
.avatar {
    line-height: 0;
    justify-content: space-around;
}

.avatar .el-icon {
    margin: 0;
}

:deep(.el-dialog__body) {
    width: 97%;
    height: 600px;
}

.dialog-footer {
    display: flex;
    justify-content: space-between;
}

.avatar-upload-preview {
    padding: 0 5em 0 5em;
}

:deep(.el-avatar) {
    position: relative;
    display: block;
}

.el-image {
    top: 50%;
    transform: translateY(-50%);
}

:deep(.el-upload-action) {
    position: absolute;
    top: 0;
    left: 0;
    display: none;
}

:deep(.el-avatar:hover .el-upload-action) {
    width: 100%;
    height: 100%;
    position: absolute;
    display: flex;
    justify-content: space-around;
    align-items: center;
    font-size: 20px;
    background-color: #000;
    background-color: rgba(0, 0, 0, 0.4)
}

.el-upload-action > .el-icon {
    cursor: pointer;
}
</style>